从 UWP 迁移到 WinUI 3 的应用通知 | 您所在的位置:网站首页 › uwp开发 azure通知 › 从 UWP 迁移到 WinUI 3 的应用通知 |
从 UWP 迁移到 WinUI 3 的应用通知
项目
06/02/2023
将应用通知代码从 UWP 迁移到 WinUI 3 时,唯一的区别在于处理通知的激活。 发送和管理应用通知完全相同。 注意 术语“toast 通知”将替换为“应用通知”。 这些术语都指 Windows 的相同功能,但随着时间的推移,我们将逐步淘汰文档中的“Toast 通知”的使用。 注意 一些信息与预发行产品相关,相应产品在商业发行之前可能会进行重大修改。 对于此处提供的信息,Microsoft 不作任何明示或暗示的担保。 激活差异 Windows 应用 SDK Windows 社区工具包 类别 UWP WinUI 3 前台激活入口点 OnActivated 调用 中的 App.xaml.cs 方法 OnLaunched 调用 中的 App.xaml.cs 方法。 后台激活入口点 作为后台任务单独处理 与前台激活相同。 OnLaunched 调用 中的 App.xaml.cs 方法。 使用 GetActivatedEventArgs 确定应用是应完全启动还是仅处理任务并退出。 窗口激活 前台激活时,窗口会自动进入前台 如果需要,必须将窗口带到前台 类别 UWP WinUI 3 前台激活入口点 OnActivated 调用 中的 App.xaml.cs 方法 订阅 ToastNotificationManagerCompat.OnActivated C++) 的事件 (或 COM 类 后台激活入口点 作为后台任务单独处理 通过 C++) 的同一 ToastNotificationManagerCompat.OnActivated 事件 (或 COM 类到达 窗口激活 前台激活时,窗口会自动进入前台 如果需要,必须将窗口带到前台 C# 应用的迁移 步骤 1:安装 NuGet 库 Windows 应用 SDK Windows 社区工具包对于 WinUI 3 应用,可以使用 AppNotificationManager 类处理通知激活。 此类由 Microsoft.WindowsAppSDK Nuget 包提供,默认情况下包含在 WinUI 3 Visual Studio 项目模板中。 在 Visual Studio 解决方案中,右键单击项目,单击“管理 NuGet 包...”,然后搜索并安装 Microsoft.Toolkit.Uwp.NotificationsNuGet 包 7.0 或更高版本。 此包添加 ToastNotificationManagerCompat API。 步骤 2:更新清单在 Package.appxmanifest 中,添加: xmlns:com 声明 xmlns:desktop 声明 在 IgnorableNamespaces 属性中,添加 com 和 desktop windows.toastNotificationActivation 的 desktop:Extension,用于声明 toast 激活器 CLSID(使用你选择的新 GUID)。 仅限 MSIX:使用步骤 4 中 GUID 的 COM 激活器的 com:Extension。 务必包括 Arguments="----AppNotificationActivated:",以便了解是从通知启动 Windows 应用 SDK Windows 社区工具包 ... ... ... ... 步骤 3:处理激活 Windows 应用 SDK Windows 社区工具包在应用的启动代码 (通常为 App.xaml.cs) 中,使用以下步骤更新代码: 在 OnLaunched 中,获取 AppNotificationManager 类的默认实例。 注册 AppNotificationManager.NotificationInvoked 事件。 调用 Microsoft.Windows.AppNotifications.AppNotificationManager.Register 注册应用以接收通知事件。 请务必在注册 NotificationInvoked 处理程序后调用此方法。 将窗口启动/激活代码重构为专用 LaunchAndBringToForegroundIfNeeded 帮助程序方法,以便可以从多个位置调用它。 创建 HandleNotification 帮助程序方法,以便可以从多个位置调用它。 调用 AppInstance.GetActivatedEventArgs 并检查返回对象的 AppActivationArguments.Kind 属性的值 ExtendedActivationKind.AppNotification。 如果激活类型不是 AppNotification ,则调用 LaunchAndBringToForegroundIfNeeded 帮助程序方法。 如果激活类型为 AppNotification ,请将 AppActivationArguments.Data 属性转换为 AppNotificationActivatedEventArgs ,并将其传递给 HandleNotification 帮助程序方法。 在 ApplicationManager.NotificationInvoked 处理程序中 HandleNotification ,调用帮助程序方法。 HandleNotification在帮助程序方法中,在执行任何与 UI 相关的代码(例如显示窗口或更新 UI)之前,请务必调度到应用或窗口调度程序 将 处理应用通知激活的旧 UWP OnActivated 代码迁移到新的 HandleNotification 帮助程序方法。 迁移的 App.xaml.cs protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { m_window = new MainWindow(); // To ensure all Notification handling happens in this process instance, register for // NotificationInvoked before calling Register(). Without this a new process will // be launched to handle the notification. AppNotificationManager notificationManager = AppNotificationManager.Default; notificationManager.NotificationInvoked += NotificationManager_NotificationInvoked; notificationManager.Register(); var activatedArgs = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs(); var activationKind = activatedArgs.Kind; if (activationKind != ExtendedActivationKind.AppNotification) { LaunchAndBringToForegroundIfNeeded(); } else { HandleNotification((AppNotificationActivatedEventArgs)activatedArgs.Data); } } private void LaunchAndBringToForegroundIfNeeded() { if (m_window == null) { m_window = new MainWindow(); m_window.Activate(); // Additionally we show using our helper, since if activated via a app notification, it doesn't // activate the window correctly WindowHelper.ShowWindow(m_window); } else { WindowHelper.ShowWindow(m_window); } } private void NotificationManager_NotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args) { HandleNotification(args); } private void HandleNotification(AppNotificationActivatedEventArgs args) { // Use the dispatcher from the window if present, otherwise the app dispatcher var dispatcherQueue = m_window?.DispatcherQueue ?? DispatcherQueue.GetForCurrentThread(); dispatcherQueue.TryEnqueue(async delegate { switch (args.Arguments["action"]) { // Send a background message case "sendMessage": string message = args.UserInput["textBox"].ToString(); // TODO: Send it // If the UI app isn't open if (m_window == null) { // Close since we're done Process.GetCurrentProcess().Kill(); } break; // View a message case "viewMessage": // Launch/bring window to foreground LaunchAndBringToForegroundIfNeeded(); // TODO: Open the message break; } }); } private static class WindowHelper { [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetForegroundWindow(IntPtr hWnd); public static void ShowWindow(Window window) { // Bring the window to the foreground... first get the window handle... var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window); // Restore window if minimized... requires DLL import above ShowWindow(hwnd, 0x00000009); // And call SetForegroundWindow... requires DLL import above SetForegroundWindow(hwnd); } }在应用的启动代码 (通常为 App.xaml.cs) ,使用以下步骤更新代码: 定义和获取应用级别 DispatcherQueue 注册 ToastNotificationManagerCompat.OnActivated 事件 将窗口启动/激活代码重构为专用 LaunchAndBringToForegroundIfNeeded 方法,以便可以从多个位置调用它 如果 ToastNotificationManagerCompat.WasCurrentProcessToastActivated() 返回 true (该方法为 true,则避免启动窗口,下一步将调用事件 OnActivated ,可以选择在事件回调) 显示窗口。 ToastNotificationManagerCompat.OnActivated在 中,在执行任何与 UI 相关的代码(例如显示窗口或更新 UI)之前,请务必调度到应用或窗口调度程序 将 处理 Toast 激活的旧 UWP OnActivated 代码迁移到新的 ToastNotificationManagerCompat.OnActivated 事件处理程序,并将任何后台任务 Toast 激活代码迁移到新的 ToastNotificationManagerCompat.OnActivated 事件处理程序。 迁移的 App.xaml.cs public static DispatcherQueue DispatcherQueue { get; private set; } protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { // Get the app-level dispatcher DispatcherQueue = global::Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread(); // Register for toast activation. Requires Microsoft.Toolkit.Uwp.Notifications NuGet package version 7.0 or greater ToastNotificationManagerCompat.OnActivated += ToastNotificationManagerCompat_OnActivated; // If we weren't launched by an app, launch our window like normal. // Otherwise if launched by a toast, our OnActivated callback will be triggered if (!ToastNotificationManagerCompat.WasCurrentProcessToastActivated()) { LaunchAndBringToForegroundIfNeeded(); } } private void LaunchAndBringToForegroundIfNeeded() { if (m_window == null) { m_window = new MainWindow(); m_window.Activate(); // Additionally we show using our helper, since if activated via a toast, it doesn't // activate the window correctly WindowHelper.ShowWindow(m_window); } else { WindowHelper.ShowWindow(m_window); } } private void ToastNotificationManagerCompat_OnActivated(ToastNotificationActivatedEventArgsCompat e) { // Use the dispatcher from the window if present, otherwise the app dispatcher var dispatcherQueue = m_window?.DispatcherQueue ?? App.DispatcherQueue; dispatcherQueue.TryEnqueue(delegate { var args = ToastArguments.Parse(e.Argument); switch (args["action"]) { // Send a background message case "sendMessage": string message = e.UserInput["textBox"].ToString(); // TODO: Send it // If the UI app isn't open if (m_window == null) { // Close since we're done Process.GetCurrentProcess().Kill(); } break; // View a message case "viewMessage": // Launch/bring window to foreground LaunchAndBringToForegroundIfNeeded(); // TODO: Open the message break; } }); } private static class WindowHelper { [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetForegroundWindow(IntPtr hWnd); public static void ShowWindow(Window window) { // Bring the window to the foreground... first get the window handle... var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(window); // Restore window if minimized... requires DLL import above ShowWindow(hwnd, 0x00000009); // And call SetForegroundWindow... requires DLL import above SetForegroundWindow(hwnd); } } 生成应用通知内容 Windows 应用 SDK Windows 社区工具包使用 Windows 应用 SDK,你仍然可以使用原始 xml 创建应用通知内容,但也可以使用新的 AppNotificationsBuilder API 创建应用通知内容,该 API 取代了 Windows 社区工具包提供的 ToastContentBuilder 类。 通过调用 AppNotificationManager.Show 发送应用通知。 不建议混合使用 Windows 社区工具包和应用 SDK API。 using Microsoft.Windows.AppNotifications; using Microsoft.Windows.AppNotifications.Builder; ... var builder = new AppNotificationBuilder() .AddText("Send a message.") .AddTextBox("textBox") .AddButton(new AppNotificationButton("Send") .AddArgument("action", "sendMessage")); var notificationManager = AppNotificationManager.Default; notificationManager.Show(builder.BuildNotification());你可以继续使用 Windows 社区工具包提供的 ToastContentBuilder 类来创建应用通知内容和在 WinUI 3 应用中发送通知。 using Microsoft.Toolkit.Uwp.Notifications; ... new ToastContentBuilder() .AddText("Send a message.") .AddInputTextBox("textBox") .AddButton(new ToastButton() .SetContent("Send") .AddArgument("action", "sendMessage")) .Show(); 相关主题 从 C# 应用发送本地 toast 通知 从 Win32 C++ WRL 应用发送本地 toast 通知 |
CopyRight 2018-2019 实验室设备网 版权所有 |